local skynet = require "skynet"
local socket = require "socket"
local crypt = require "crypt"

local WATCHDOG

local CMD = {}
local client_fd
local client_addr = nil

local aplayerid = 0

local function send_data(fd, pack)
    local package = string.pack(">s2", pack)
    socket.write(fd, package)
end

local function send_package(fd, pack)
	local package = string.pack(">s2", pack)
	socket.write(fd, package)
end

local function OnLogin(smsg, sz)
    local playerid = string.unpack("<I4", smsg, 5) 
    aplayerid = playerid
    skynet.error("agent OnLogin playerid="..playerid.." client_fd="..client_fd)
    skynet.call(WATCHDOG, "lua", "login", playerid, client_fd)
end

local function OnLogout(smsg, sz)
    local playerid = string.unpack("<I4", smsg, 5) 
    aplayerid = 0
    skynet.call(WATCHDOG, "lua", "logout", playerid)
end

local function OnGetPlay(t)
    local recvt = skynet.call(WATCHDOG, "lua", "getPlay", t)
    return recvt
end

local function OnSendVoice(smsg, sz)
    local playert = {}
    local logstr = ""
    for i=1, 16 do
        start = 17 + ((i-1)*4)
        playert[i] = string.unpack("<I4", smsg, start) 
        logstr=logstr.." "..playert[i]
        --skynet.error("id "..playert[i].." start "..start)
    end
    
    skynet.error("will send to playid: "..logstr)

    local recvt = OnGetPlay(playert)
    --return smsg
    local package = string.pack(">s2", smsg)
    for i=1, 16 do
        if recvt[i] ~= nil then
            skynet.error(" send data: "..sz.." package = "..sz.." fd= "..recvt[i])
            local ret = socket.write(tonumber(recvt[i]), package)
        end
    end
    
    return nil
end

local function error_toClose()
    skynet.call(WATCHDOG, "lua", "close", client_fd)
end

local function bin2hex(s)
    s=string.gsub(s,"(.)",function (x) return string.format("%02X ",string.byte(x)) end)
    return s
end

local function out(msg) 
    skynet.error(bin2hex(msg))
end


local function request(smsg, sz)
    if sz < 4 then
        skynet.error("close fd,find error packet sz:"..sz)
        error_toClose()
        return nil
    end

    local mcmd,scmd = string.unpack(">I2>I2", smsg, 1) 
    if mcmd > 500 or scmd > 3000 then
        skynet.error("close fd: ->w mcmd="..mcmd.." scmd="..scmd.." sz="..sz)
        error_toClose()
        return nil
    end

    --skynet.error("request : ->w mcmd="..mcmd.." scmd="..scmd.." sz="..sz)

    if mcmd == 400 then 
        if scmd == 1001 or scmd == 1002 then
            OnLogin(smsg, sz)
            return nil
        end

        if scmd == 1003 then
            
            return OnSendVoice(smsg, sz)
        end
        
        if scmd == 1004 then
            OnLogout(smsg, sz)
            return nil
        end
    end

    return nil
end


skynet.register_protocol {
	name = "client",
	id = skynet.PTYPE_CLIENT,
    unpack = function(msg,sz) 
        return  skynet.tostring(msg,sz), sz  
    end,
	dispatch = function (_, _, smsg, sz)
		local ok, result  = pcall(request, smsg, sz)
		if ok then
			if result then
				send_package(client_fd, result)
			end
		else
			skynet.error(result)
		end
	end
}

function CMD.start(conf)
	local fd = conf.client
	local gate = conf.gate
	WATCHDOG = conf.watchdog
    local s, e = string.find(conf.clientaddr, ":")
    client_addr = string.sub(conf.clientaddr, 1, s-1) 

    skynet.error("CMD.start ip="..client_addr)

	client_fd = fd
	skynet.call(gate, "lua", "forward", fd)
end

function CMD.disconnect()
    skynet.send(WATCHDOG, "lua", "logout", aplayerid)
    skynet.exit()
end

skynet.start(function()
	skynet.dispatch("lua", function(_,_, command, ...)
		local f = CMD[command]
		skynet.ret(skynet.pack(f(...)))
	end)
end)
